home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / connx-1.001 / connx-1~ / xconnect.c < prev    next >
C/C++ Source or Header  |  1995-02-11  |  26KB  |  1,010 lines

  1. #include <X11/Xlib.h>
  2. #include <X11/Xutil.h>
  3. #include <X11/Xos.h>
  4. #include <X11/Xatom.h>
  5. #include <X11/Xresource.h>
  6. #include <pwd.h>
  7. #include "xconnect.h"
  8. #include "connect.h"
  9.  
  10. #ifdef DEBUG
  11. #define PRINTF(x) printf x
  12. #else
  13. #define PRINTF(x)
  14. #endif
  15.  
  16. /* the globals */
  17. Pixmap pix;
  18. Pixmap erase_circ;
  19. Window win;
  20. Display *display;
  21. int screen_num;
  22. GC open_text, draw_board, clear_board, draw_text, draw_circ, draw_shadow;
  23. int width, height, block_width, block_height, line_width;
  24. int player_pixels[MAX_PLAYERS];
  25. XFontStruct *the_font;
  26. board the_board;
  27. extern char *program_name;
  28. XrmDatabase dbase;
  29. int game_winner;
  30. coord win_start, win_end;
  31. int game_over = False;
  32. int players_turn;
  33. game_start game_attrib;
  34. int allocated = False;
  35.  
  36. /* some common colors */
  37. int highlight, background, foreground, shadow;
  38.  
  39. /*prototypes*/
  40. void make_board ();
  41. void create_pixmaps ();
  42. void create_gcs ();
  43. void set_block_size ();
  44. void resize (int w, int h);
  45. void free_pixmaps ();
  46. void free_gcs ();
  47. void draw_piece (int row, int col, int pixel);
  48. void change_color (int fg, int bg, GC change);
  49. void draw_move (coord new_pos, coord old_pos);
  50. int get_color (char *name);
  51. char *get_resource (char *resource);
  52. coord get_cursor_pos (int x, int y);
  53. void get_home_dir (char *dest);
  54. void list_players ();
  55. void load_font ();
  56. void draw_final ();
  57. void draw_clock (time_t tleft);
  58.  
  59. /***************************************************************************/
  60. /*MAIN ROUTINES************************************************************/
  61. /*************************************************************************/
  62.  
  63. /*
  64.  * open the display and window
  65.  */
  66. int
  67. X_open (char *pDisplay_name)
  68. {
  69.   XGCValues gc_values;
  70.   char xdef[256];
  71.   XrmDatabase dbase_temp;
  72.   XTextProperty win_name;
  73.   /* connect to server */
  74.   if ((display = XOpenDisplay (pDisplay_name)) == NULL)
  75.  
  76.     {
  77.  
  78.       printf ("Cannot connect to X Server: %s\n", pDisplay_name);
  79.       return -1;
  80.  
  81.     }
  82.   screen_num = DefaultScreen (display);
  83.  
  84.   /* load resource file */
  85.   XrmInitialize ();
  86.   dbase = XrmGetFileDatabase (RESOURCE_FILE);
  87.   get_home_dir (xdef);
  88.   strcat (xdef, "/.Xdefaults");
  89.   dbase_temp = XrmGetFileDatabase (xdef);
  90.   XrmMergeDatabases (dbase_temp, &dbase);
  91.  
  92.   highlight = get_color (get_resource ("highlight"));
  93.   foreground = get_color (get_resource ("foreground"));
  94.   background = get_color (get_resource ("background"));
  95.   shadow = get_color (get_resource ("shadow"));
  96.  
  97.   /* open the window */
  98.   width = WIN_WIDTH;
  99.   height = WIN_HEIGHT;
  100.   win = XCreateSimpleWindow (display, RootWindow (display, screen_num),
  101.                  X_WIN, Y_WIN, width, height, BORDER_WIDTH,
  102.                  BlackPixel (display, screen_num),
  103.                  background);
  104.  
  105.  
  106.   load_font ();
  107.   gc_values.foreground = foreground;
  108.   gc_values.graphics_exposures = False;
  109.   gc_values.font = the_font->fid;
  110.   open_text = XCreateGC (display, win, GCForeground | GCBackground |
  111.              GCFont | GCGraphicsExposures, &gc_values);
  112.  
  113.   /* draw title on opening screen */
  114.   XDrawString (display, win, open_text, width / 2 - XTextWidth (the_font,
  115.          TITLE_STRING, strlen (TITLE_STRING)), height / 2, TITLE_STRING,
  116.            strlen (TITLE_STRING));
  117.  
  118.   XStringListToTextProperty (&program_name, 1, &win_name);
  119.   XSetWMName (display, win, &win_name);
  120.  
  121.   XMapWindow (display, win);
  122.  
  123.   XSelectInput (display, win, ExposureMask | KeyPressMask
  124.         | StructureNotifyMask);
  125.   XFlush (display);
  126.  
  127.   return 0;
  128. }
  129.  
  130. /****************************************************************************/
  131.  
  132. /*
  133.  * close window and display
  134.  */
  135. int
  136. X_close ()
  137. {
  138.   XDestroyWindow (display, win);
  139.   XCloseDisplay (display);
  140.   return 0;
  141. }
  142.  
  143. /****************************************************************************/
  144.  
  145. /*
  146.  * allocate resources and draw board
  147.  */
  148. int
  149. X_allocate (game_start game_attr)
  150. {
  151.   int i;
  152.   char resource[20];
  153.  
  154.   if (allocated == True)    /* deallocate resources from previous game */
  155.     X_deallocate ();
  156.  
  157.   allocated = True;
  158.  
  159.   /* set globals */
  160.   game_attrib = game_attr;
  161.   set_block_size ();
  162.   bzero (the_board, sizeof (board));
  163.   game_over = False;
  164.   players_turn = 1;
  165.  
  166.   /* allocate player colors */
  167.   for (i = 0; i < game_attrib.num_players; i++)
  168.     {
  169.       sprintf (resource, "team%d", game_attrib.team_numbers[i]);
  170.       player_pixels[i] = get_color (get_resource (resource));
  171.     }
  172.  
  173.   load_font ();
  174.   create_pixmaps ();
  175.   create_gcs ();
  176.   make_board ();
  177.  
  178.   XFlush (display);
  179.  
  180.   return 0;
  181. }
  182.  
  183. /*****************************************************************************/
  184.  
  185. /*
  186.  * free resources used in game
  187.  */
  188. int
  189. X_deallocate ()
  190. {
  191.  
  192.   if (allocated == True)
  193.  
  194.     {
  195.       free_pixmaps ();
  196.       free_gcs ();
  197.       XFreeFont (display, the_font);
  198.       allocated = False;
  199.       return 0;
  200.     }
  201.   allocated = False;
  202. }
  203.  
  204. /****************************************************************************/
  205.  
  206. /*
  207.  * get players move
  208.  */
  209. int
  210. X_get_player_move (coord * move)
  211. {
  212.   XEvent event;
  213.   int move_found = False;
  214.   Window root, child;
  215.   int root_x, root_y, win_x, win_y;
  216.   unsigned int buttons;
  217.   coord position;
  218.   coord new_pos;
  219.   coord null_move =
  220.   {-1, -1};
  221.   int cnt;
  222.   char buf[5];
  223.   KeySym keysym;
  224.   time_t the_time, time_left, old_time_left;
  225.   int rc = 0;
  226.  
  227.   X_show_turn (game_attrib.your_number);
  228.  
  229.   XSelectInput (display, win, ExposureMask | ButtonPressMask
  230.         | KeyPressMask | PointerMotionMask | StructureNotifyMask);
  231.   XQueryPointer (display, win, &root, &child, &root_x,
  232.          &root_y, &win_x, &win_y, &buttons);
  233.   change_color (player_pixels[game_attrib.your_number - 1], background,
  234.         draw_circ);
  235.  
  236.   position = get_cursor_pos (win_x, win_y);
  237.  
  238.   if (position.row != -1 && position.column != -1)
  239.     draw_move (position, null_move);
  240.  
  241.   if (game_attrib.timeout != 0)
  242.     the_time = time (NULL);
  243.  
  244.   while (move_found == False)
  245.     {
  246.  
  247.       if (XPending (display) > 0)
  248.     {
  249.       XNextEvent (display, &event);
  250.       switch (event.type)
  251.         {
  252.         case KeyPress:
  253.           cnt = XLookupString (&event.xkey, buf, 1, &keysym, NULL);
  254.           if (buf[0] == 'q' || buf[0] == 'Q')
  255.         return QUIT;
  256.           break;
  257.         case ButtonPress:
  258.           *move = get_cursor_pos (event.xbutton.x, event.xbutton.y);
  259.           if (move->row != -1 && move->column != -1)
  260.         {
  261.           move_found = True;
  262.           move->row--;
  263.           move->column--;
  264.           draw_move (null_move, position);
  265.           if (game_attrib.timeout != 0)
  266.             draw_clock (-1);
  267.         }
  268.           break;
  269.         case MotionNotify:
  270.           new_pos = get_cursor_pos (event.xmotion.x, event.xmotion.y);
  271.           if (new_pos.row != -1
  272.           && new_pos.column != -1 &&
  273.           ((new_pos.row != position.row && game_attrib.game_type
  274.             == NOGRAVITY)
  275.            || new_pos.column != position.column))
  276.         {
  277.           draw_move (new_pos, position);
  278.           position = new_pos;
  279.         }
  280.  
  281.           break;
  282.         case Expose:
  283.           XCopyArea (display, pix, win, draw_board, event.xexpose.x,
  284.          event.xexpose.y, event.xexpose.width, event.xexpose.height,
  285.              event.xexpose.x, event.xexpose.y);
  286.           XFlush (display);
  287.           break;
  288.         case ConfigureNotify:
  289.           draw_move (null_move, position);
  290.           position.row = -1;
  291.           resize (event.xconfigure.width, event.xconfigure.height);
  292.           break;
  293.         default:
  294.           break;
  295.         }
  296.     }
  297.  
  298.       /* check if server cancelled move*/
  299.       if (move_cancelled () == 1)
  300.     {
  301.       /* client sends forfeit message to server */
  302.       rc = FORFEIT;
  303.       move_found = True;
  304.       draw_move (null_move, position);
  305.       draw_clock (-1);
  306.     }
  307.  
  308.       /* update timer indicating how mush time left to move*/
  309.       if (move_found == False && game_attrib.timeout != 0)
  310.     {
  311.       time_left = game_attrib.timeout - (time (NULL) - the_time);
  312.       if (time_left != old_time_left)
  313.         {
  314.           draw_clock (time_left);
  315.           old_time_left = time_left;
  316.         }
  317.       if (time_left <= 0)
  318.         {
  319.           /* client sends forfeit message to server */
  320.           rc = FORFEIT;
  321.           move_found = True;
  322.           draw_move (null_move, position);
  323.           draw_clock (-1);
  324.         }
  325.     }
  326.     }
  327.   XSelectInput (display, win, ExposureMask | StructureNotifyMask
  328.         | KeyPressMask);
  329.  
  330.   return rc;
  331. }
  332.  
  333. /**************************************************************************/
  334.  
  335. /*
  336.  * animate a piece moving into a position on the board
  337.  */
  338. int
  339. X_add_to_board (coord move, int player_num)
  340. {
  341.   int row_start;
  342.   int anim;
  343.   change_color (player_pixels[player_num - 1], background, draw_circ);
  344.  
  345.   the_board[move.row][move.column] = player_num;
  346.   move.row++;
  347.   move.column++;
  348.   for (row_start = 0; row_start <= (move.row * block_height);
  349.        row_start = row_start + ANIM_PIXELS)
  350.     {
  351.       if (row_start != 0)
  352.     /* erase old circle */
  353.     XCopyArea (display, erase_circ, pix, draw_board, 0, 0,
  354.            block_width, block_height,
  355.            (move.column * block_width), row_start - ANIM_PIXELS);
  356.  
  357.       /* save area */
  358.       XCopyArea (display, pix, erase_circ, draw_board,
  359.          (move.column * block_width),
  360.          row_start, block_width, block_height, 0, 0);
  361.  
  362.       /* draw new circle */
  363.       XFillArc (display, pix, draw_circ, (move.column * block_width)
  364.         + line_width / 2
  365.         ,row_start + line_width / 2, block_width - line_width + 1,
  366.         block_height - line_width + 1, 0, 360 * 64);
  367.  
  368.       /* draw line from board square */
  369.       XDrawLine (display, pix, draw_board, (move.column * block_width),
  370.          ((row_start / block_height) + 1) * block_height,
  371.          (move.column + 1) * block_width,
  372.          ((row_start / block_height) + 1) * block_height);
  373.  
  374.       /* copy to window */
  375.       XCopyArea (display, pix, win, draw_board, (move.column * block_width),
  376.          row_start - ANIM_PIXELS,
  377.          block_width, block_height + ANIM_PIXELS,
  378.          (move.column * block_width), row_start - ANIM_PIXELS);
  379.       XFlush (display);
  380.  
  381.     }
  382.   /* make sure piece lands in proper place */
  383.   row_start = row_start - ANIM_PIXELS;
  384.   anim = (move.row * block_height) - row_start;
  385.   if (anim != 0)
  386.     {
  387.       XCopyArea (display, erase_circ, pix, draw_board, 0, 0,
  388.          block_width, block_height,
  389.          (move.column * block_width), row_start);
  390.  
  391.       XFillArc (display, pix, draw_circ, (move.column * block_width) +
  392.         line_width / 2
  393.         ,(move.row * block_height) + line_width / 2, block_width
  394.         - line_width + 1,
  395.         block_height - line_width + 1, 0, 360 * 64);
  396.  
  397.       XCopyArea (display, pix, win, draw_board, (move.column * block_width),
  398.      (move.row * block_height) - anim, block_width, block_height + anim,
  399.          (move.column * block_width), (move.row * block_height) - anim);
  400.       XFlush (display);
  401.     }
  402.  
  403.   return 0;
  404.  
  405. }
  406.  
  407. /****************************************************************************/
  408.  
  409. /*
  410.  * tell user that move was bad
  411.  */
  412. int
  413. X_bad_move ()
  414. {
  415.   XBell (display, 100);
  416.   XFlush (display);
  417.   return 0;
  418. }
  419.  
  420. /****************************************************************************/
  421.  
  422. /*
  423.  * indicate game is over
  424.  */
  425. int
  426. X_game_end (int winner, coord start, coord end)
  427. {
  428.   game_over = True;
  429.   win_start = start;
  430.   game_winner = winner;
  431.   win_end = end;
  432.   win_start.row++;
  433.   win_start.column++;
  434.   win_end.row++;
  435.   win_end.column++;
  436.  
  437.   draw_final ();
  438.   return 0;
  439.  
  440. }
  441.  
  442.  
  443.  
  444. /***************************************************************************/
  445.  
  446. /*
  447.  * handle expose and resize events
  448.  */
  449. int
  450. X_handle_events ()
  451. {
  452.   XEvent event;
  453.   int cnt;
  454.   char buf[5];
  455.   KeySym keysym;
  456.  
  457.   while (XPending (display) > 0)
  458.     {
  459.       XNextEvent (display, &event);
  460.       switch (event.type)
  461.     {
  462.     case KeyPress:
  463.       cnt = XLookupString (&event.xkey, buf, 1, &keysym, NULL);
  464.       if (buf[0] == 'q' || buf[0] == 'Q')
  465.         return QUIT;
  466.       break;
  467.     case ConfigureNotify:
  468.       if (allocated == True)
  469.         resize (event.xconfigure.width, event.xconfigure.height);
  470.       else
  471.         {
  472.           width = event.xconfigure.width;
  473.           height = event.xconfigure.height;
  474.         }
  475.       break;
  476.     case Expose:
  477.       if (allocated == True)
  478.         XCopyArea (display, pix, win, draw_board, event.xexpose.x,
  479.          event.xexpose.y, event.xexpose.width, event.xexpose.height,
  480.                event.xexpose.x, event.xexpose.y);
  481.       else
  482.         {
  483.           XClearWindow (display, win);
  484.           XDrawString (display, win, open_text, width / 2 - XTextWidth (the_font,
  485.           TITLE_STRING, strlen (TITLE_STRING)), height / 2, TITLE_STRING,
  486.                strlen (TITLE_STRING));
  487.         }
  488.       XFlush (display);
  489.       break;
  490.     default:
  491.       break;
  492.     }
  493.     }
  494.   return 0;
  495.  
  496. }
  497.  
  498. /***********************************************************************/
  499.  
  500. /*
  501.  * change player list to indicate whose turn it is
  502.  */
  503. int
  504. X_show_turn (int player_no)
  505. {
  506.   players_turn = player_no;
  507.   list_players ();
  508.   XCopyArea (display, pix, win, draw_board, block_width,
  509.          game_attrib.num_rows * block_height,
  510.          width, block_height * 2, block_width,
  511.          game_attrib.num_rows * block_height);
  512.  
  513. }
  514.  
  515. /***************************************************************************/
  516. /*internal subroutines*******************************************************/
  517. /****************************************************************************/
  518.  
  519. /*
  520.  * set block width, height
  521.  */
  522. void
  523. set_block_size ()
  524. {
  525.   block_width = width / (game_attrib.num_columns + 2);
  526.   if (block_width < 1)
  527.     block_width = 1;
  528.   block_height = height / (game_attrib.num_rows + 3);
  529.   if (block_height < 1)
  530.     block_height = 1;
  531.   line_width = block_width / 10;
  532.   if (line_width < 1)
  533.     line_width = 1;
  534.   if (line_width % 2 == 0)
  535.     line_width++;
  536. }
  537.  
  538. /****************************************************************************/
  539.  
  540. /*
  541.  * create the pixmaps
  542.  */
  543. void
  544. create_pixmaps ()
  545.  
  546. {
  547.  
  548.   /* create Pixmaps */
  549.   pix = XCreatePixmap (display, win, width, height,
  550.                DefaultDepth (display, screen_num));
  551.   erase_circ = XCreatePixmap (display, win, block_width,
  552.               block_height, DefaultDepth (display, screen_num));
  553. }
  554.  
  555. /*************************************************************************/
  556.  
  557. /*
  558.  * create GCs
  559.  */
  560. void
  561. create_gcs ()
  562. {
  563.   XGCValues gc_values;
  564.  
  565.   /* create GCs */
  566.   gc_values.foreground = foreground;
  567.   gc_values.background = 0;
  568.   gc_values.line_width = line_width;
  569.   gc_values.join_style = JoinMiter;
  570.   gc_values.graphics_exposures = False;
  571.   draw_board = XCreateGC (display, pix, GCForeground | GCBackground
  572.               | GCLineWidth | GCJoinStyle
  573.               | GCGraphicsExposures, &gc_values);
  574.   gc_values.font = the_font->fid;
  575.   draw_text = XCreateGC (display, pix, GCForeground | GCBackground |
  576.              GCFont | GCGraphicsExposures, &gc_values);
  577.   draw_circ = XCreateGC (display, pix, 0, NULL);
  578.   gc_values.foreground = background;
  579.   gc_values.background = 0;
  580.   clear_board = XCreateGC (display, pix, GCForeground |
  581.                GCBackground | GCGraphicsExposures, &gc_values);
  582.   gc_values.foreground = shadow;
  583.   draw_shadow = XCreateGC (display, pix, GCForeground | GCBackground
  584.                | GCLineWidth | GCJoinStyle | GCGraphicsExposures,
  585.                &gc_values);
  586. }
  587.  
  588. /*************************************************************************/
  589.  
  590. /*
  591.  * create the board
  592.  */
  593. void
  594. make_board ()
  595. {
  596.   int row_start, col_start, i;
  597.   int offset, num = 0;
  598.   XSegment shad[MAX_ROW + MAX_COL + 2], board[MAX_ROW + MAX_COL + 2];
  599.  
  600.   offset = line_width;
  601.  
  602.   /* clear board */
  603.   XFillRectangle (display, pix, clear_board, 0, 0, width, height);
  604.  
  605.   /*build the board */
  606.   /*rectangles extend one past block */
  607.  
  608.  
  609.   num = 0;
  610.   for (col_start = block_width; col_start / block_width <=
  611.        (game_attrib.num_columns + 1); col_start = col_start + block_width)
  612.     {
  613.       shad[num].x1 = col_start - offset;
  614.       shad[num].y1 = block_height + offset - (line_width / 2);
  615.       shad[num].x2 = col_start - offset;
  616.       shad[num].y2 = ((game_attrib.num_rows + 1) * block_height) +
  617.     offset + (line_width / 2);
  618.       board[num].x1 = col_start;
  619.       board[num].y1 = block_height - (line_width / 2);
  620.       board[num].x2 = col_start;
  621.       board[num++].y2 = (game_attrib.num_rows + 1) * block_height
  622.     + (line_width / 2);
  623.     }
  624.  
  625.  
  626.   for (row_start = block_height; row_start / block_height
  627.        <= (game_attrib.num_rows + 1); row_start = row_start + block_height)
  628.     {
  629.       shad[num].x1 = block_width - offset - (line_width / 2);
  630.       shad[num].y1 = row_start + offset;
  631.       shad[num].x2 = ((game_attrib.num_columns + 1) * block_width)
  632.     - offset + (line_width / 2);
  633.       shad[num].y2 = row_start + offset;
  634.       board[num].x1 = block_width - (line_width / 2);
  635.       board[num].y1 = row_start;
  636.       board[num].x2 = (game_attrib.num_columns + 1) * block_width +
  637.     (line_width / 2);
  638.       board[num++].y2 = row_start;
  639.     }
  640.  
  641.   XDrawSegments (display, pix, draw_shadow, shad, num);
  642.   XDrawSegments (display, pix, draw_board, board, num);
  643.  
  644.   list_players ();
  645.  
  646.   XCopyArea (display, pix, win, draw_board, 0, 0, width, height, 0, 0);
  647.  
  648. }
  649.  
  650. /****************************************************************************/
  651.  
  652. /*
  653.  * change color of circles drawn
  654.  */
  655. void
  656. change_color (int fg, int bg, GC change)
  657. {
  658.   XGCValues gc_values;
  659.  
  660.   gc_values.foreground = fg;
  661.   gc_values.background = bg;
  662.   XChangeGC (display, change, GCForeground | GCBackground, &gc_values);
  663. }
  664.  
  665.  
  666. /***************************************************************************/
  667.  
  668. /*
  669.  * draw move selection on top of board
  670.  */
  671. void
  672. draw_move (coord new_pos, coord old_pos)
  673. {
  674.  
  675.   /* erase old position */
  676.   if (old_pos.row != -1 && old_pos.column != -1)
  677.     XCopyArea (display, erase_circ, pix, draw_board, 0, 0,
  678.            block_width, block_height,
  679.            (old_pos.column * block_width), (old_pos.row * block_height));
  680.  
  681.  
  682.   /* draw new position */
  683.   if (new_pos.row != -1 && new_pos.column != -1)
  684.     {
  685.       XCopyArea (display, pix, erase_circ, draw_board,
  686.            (new_pos.column * block_width), (new_pos.row * block_height),
  687.          block_width, block_height, 0, 0);
  688.  
  689.       XFillArc (display, pix, draw_circ, (new_pos.column * block_width)
  690.         + line_width / 2, (new_pos.row * block_height) + line_width / 2,
  691.         block_width - line_width + 1,
  692.         block_height - line_width + 1, 0, 360 * 64);
  693.     }
  694.  
  695.   /* copy to window */
  696.  
  697.   if (old_pos.row != -1 && old_pos.column != -1)
  698.     XCopyArea (display, pix, win, draw_board, (old_pos.column * block_width),
  699.            (old_pos.row * block_height), block_width, block_height,
  700.            (old_pos.column * block_width), (old_pos.row * block_height));
  701.  
  702.   if (new_pos.row != -1 && new_pos.column != -1)
  703.     XCopyArea (display, pix, win, draw_board, (new_pos.column * block_width),
  704.            (new_pos.row * block_height), block_width, block_height,
  705.            (new_pos.column * block_width), (new_pos.row * block_height));
  706.  
  707.  
  708.   XFlush (display);
  709. }
  710.  
  711. /****************************************************************************/
  712.  
  713. /*
  714.  * draw indication of winner
  715.  */
  716. void
  717. draw_final ()
  718. {
  719.   coord win_pos;
  720.   int wait;
  721.   XEvent event;
  722.   char winner_str[80];
  723.   win_pos.row = game_attrib.num_rows + 2;
  724.   win_pos.column = 1;
  725.  
  726.   if (game_winner < 0)
  727.     XDrawString (display, pix, draw_text, ((win_pos.column) * block_width),
  728.          ((win_pos.row + 1) * block_height) - block_height / 4,
  729.          (game_winner == -1 ? TIE_STRING : CANCEL_STRING),
  730.          (game_winner == -1 ? strlen (TIE_STRING) :
  731.           strlen (CANCEL_STRING)));
  732.   else
  733.     {
  734.       /* draw line connecting winning pieces on pixmap and window*/
  735.       XDrawLine (display, win, draw_board, (win_start.column * block_width)
  736.          + (block_width / 2),
  737.          (win_start.row * block_height) + (block_height / 2),
  738.          (win_end.column * block_width) + (block_width / 2),
  739.          (win_end.row * block_height) + (block_height / 2));
  740.  
  741.       XDrawLine (display, pix, draw_board, (win_start.column * block_width)
  742.          + (block_width / 2),
  743.          (win_start.row * block_height) + (block_height / 2),
  744.          (win_end.column * block_width) + (block_width / 2),
  745.          (win_end.row * block_height) + (block_height / 2));
  746.  
  747.       change_color (player_pixels[game_winner - 1], background, draw_text);
  748.  
  749.       sprintf (winner_str, "%s%s", game_attrib.players[game_winner - 1],
  750.            WINNER_STRING);
  751.       XDrawString (display, pix, draw_text, ((win_pos.column) *
  752.                 block_width), ((win_pos.row + 1) * block_height)
  753.            - block_height / 4, winner_str, strlen (winner_str));
  754.     }
  755.  
  756.   /* copy text area to window */
  757.   XCopyArea (display, pix, win, draw_board, (win_pos.column * block_width),
  758.          (win_pos.row * block_height),
  759.          width, block_height, (win_pos.column * block_width),
  760.          (win_pos.row * block_height));
  761.   XFlush (display);
  762.  
  763. }
  764.  
  765. /***************************************************************************/
  766.  
  767. /*
  768.  * x coordinate to column number
  769.  */
  770. coord
  771. get_cursor_pos (int x, int y)
  772. {
  773.   coord pos;
  774.  
  775.   pos.column = x / block_width;
  776.   pos.row = y / block_height;
  777.   if (pos.column == 0 || (pos.column > game_attrib.num_columns))
  778.     pos.column = -1;
  779.   if (game_attrib.game_type == GRAVITY)
  780.     pos.row = 0;
  781.   else if (pos.row == 0 || (pos.row > game_attrib.num_rows))
  782.     pos.row = -1;
  783.   return pos;
  784. }
  785.  
  786. /****************************************************************************/
  787. void
  788. free_pixmaps ()
  789. {
  790.   XFreePixmap (display, pix);
  791.   XFreePixmap (display, erase_circ);
  792. }
  793.  
  794. /*****************************************************************************/
  795. void
  796. free_gcs ()
  797. {
  798.   XFreeGC (display, draw_board);
  799.   XFreeGC (display, clear_board);
  800.   XFreeGC (display, draw_text);
  801.   XFreeGC (display, draw_circ);
  802.   XFreeGC (display, draw_shadow);
  803. }
  804.  
  805. /**************************************************************************/
  806. /*
  807.  * draw a piece into pixmap
  808.  */
  809. void
  810. draw_piece (int row, int col, int pixel)
  811. {
  812.   change_color (pixel, background, draw_circ);
  813.   XFillArc (display, pix, draw_circ, (col * block_width)
  814.         + line_width / 2, (row * block_height) + line_width / 2,
  815.         block_width - line_width + 1,
  816.         block_height - line_width + 1, 0, 360 * 64);
  817. }
  818.  
  819. /****************************************************************************/
  820.  
  821. /*
  822.  * resize the window
  823.  */
  824. void
  825. resize (int w, int h)
  826. {
  827.   int i, j;
  828.   XGCValues values;
  829.   int old_line_width;
  830.  
  831.   /* only handle resize */
  832.   if (w != width || h != height)
  833.     {
  834.  
  835.       /* make sure new size is big enough */
  836.       if ((w >= ((line_width + 1) * (game_attrib.num_columns + 2)))
  837.       && (h >= ((line_width + 1) * (game_attrib.num_rows + 3))))
  838.  
  839.     {
  840.       width = w;
  841.       height = h;
  842.  
  843.       old_line_width = line_width;
  844.       set_block_size ();
  845.       XFreeFont (display, the_font);
  846.       load_font ();
  847.       values.font = the_font->fid;
  848.       XChangeGC (display, draw_text, GCFont, &values);
  849.       if (line_width != old_line_width)
  850.         {
  851.           values.line_width = line_width;
  852.           XChangeGC (display, draw_board, GCLineWidth, &values);
  853.           XChangeGC (display, draw_shadow, GCLineWidth, &values);
  854.         }
  855.       free_pixmaps ();
  856.       create_pixmaps ();
  857.       make_board ();
  858.  
  859.       /*redraw already placed game pieces */
  860.       for (i = 0; i < game_attrib.num_rows; i++)
  861.         for (j = 0; j < game_attrib.num_columns; j++)
  862.           if (the_board[i][j] != 0)
  863.         draw_piece (i + 1, j + 1, player_pixels[the_board[i][j] - 1]);
  864.  
  865.       if (game_over == True)
  866.         draw_final ();
  867.  
  868.       /*expose will come after a resize */
  869.  
  870.     }
  871.     }
  872. }
  873.  
  874. /*****************************************************************************/
  875.  
  876. char *
  877. get_resource (char *resource)
  878. {
  879.   char name[50];
  880.   char *str_type[20];
  881.   XrmValue xval;
  882.  
  883.   sprintf (name, "%s.%s", program_name, resource);
  884.   if (!XrmGetResource (dbase, name, NULL, str_type, &xval))
  885.     {
  886.       printf ("resource (%s) not found\n", resource);
  887.       return NULL;
  888.     }
  889.   return xval.addr;
  890.  
  891. }
  892.  
  893. /****************************************************************************/
  894.  
  895. int
  896. get_color (char *name)
  897. {
  898.  
  899.   Colormap cmap;
  900.   XColor def;
  901.  
  902.   cmap = DefaultColormap (display, screen_num);
  903.   if (!XParseColor (display, cmap, name, &def))
  904.     {
  905.       printf ("color (%s) not found\n", name);
  906.       return BlackPixel (display, screen_num);
  907.     }
  908.   XAllocColor (display, cmap, &def);
  909.   return def.pixel;
  910. }
  911.  
  912.  
  913. /*************************************************************************/
  914.  
  915. void
  916. get_home_dir (char *dest)
  917.  
  918. {
  919.   struct passwd *pInfo;
  920.  
  921.   pInfo = getpwuid (getuid ());
  922.   strcpy (dest, pInfo->pw_dir);
  923. }
  924.  
  925. /*****************************************************************************/
  926.  
  927. void
  928. list_players ()
  929. {
  930.   int x, y, i;
  931.   char the_player[NAME_SIZE + 1];
  932.  
  933.   x = block_width;
  934.   y = ((game_attrib.num_rows + 2) * block_height) - block_height / 4;
  935.  
  936.   for (i = -1; i < game_attrib.num_players; i++)
  937.     {
  938.       change_color ((i == -1) ? foreground : player_pixels[i],
  939.             (i == (players_turn - 1)) ? highlight : background,
  940.             draw_text);
  941.       sprintf (the_player, "%s", (i == -1) ? PLAYER_STRING :
  942.            game_attrib.players[i]);
  943.       XDrawImageString (display, pix, draw_text, x, y,
  944.             the_player, strlen (the_player));
  945.       x = x + XTextWidth (the_font, the_player, strlen (the_player));
  946.       XDrawString (display, pix, draw_text, x, y, " ", 1);
  947.       x = x + XTextWidth (the_font, " ", 1);
  948.     }
  949.  
  950.   /* change color back */
  951.   change_color (player_pixels[game_attrib.your_number - 1], background,
  952.         draw_text);
  953. }
  954.  
  955. /*****************************************************************************/
  956.  
  957. void
  958. load_font ()
  959. {
  960.   int res_x, res_y, pixels;
  961.   char font_string[100];
  962.  
  963.   res_x = DisplayWidth (display, screen_num) / (DisplayWidthMM (display,
  964.                             screen_num) / 25.4);
  965.  
  966.   res_y = DisplayHeight (display, screen_num) / (DisplayHeightMM (display,
  967.                             screen_num) / 25.4);
  968.  
  969.   pixels = block_height / 2;
  970.   sprintf (font_string, "-*-helvetica-bold-*-*-*-%d-*-%d-%d-*-*-*-*",
  971.        pixels, res_x, res_y);
  972.  
  973.   the_font = XLoadQueryFont (display, font_string);
  974.   PRINTF (("%s %d\n", font_string, the_font));
  975.   if (the_font == 0)
  976.     the_font = XLoadQueryFont (display, "9x15");
  977.  
  978. }
  979.  
  980. /*****************************************************************************/
  981.  
  982. /*
  983.  * draw the timer
  984.  */
  985. void
  986. draw_clock (time_t tleft)
  987. {
  988.   char time_str[20];
  989.   int x, y, len;
  990.  
  991.   x = block_width;
  992.   y = (game_attrib.num_rows + 3) * block_height - (block_height / 4);
  993.   len = XTextWidth (the_font, TIME_STRING, strlen (TIME_STRING));
  994.  
  995.   if (tleft != -1)
  996.     {
  997.       /* erase old time */
  998.       XClearArea (display, win, x + len, y - block_height / 2, width - (x + len),
  999.           block_height, False);
  1000.  
  1001.       /* draw new time */
  1002.       sprintf (time_str, "%s%d   ", TIME_STRING, tleft);
  1003.       XDrawImageString (display, win, draw_text, x, y, time_str,
  1004.             strlen (time_str));
  1005.     }
  1006.   else
  1007.     XClearArea (display, win, x, y - block_height / 2, width, block_height, False);
  1008.  
  1009. }
  1010.